<template>
  <a-select :default-active-first-option="false"
            :filter-option="false"
            :options="selectOptions"
            :placeholder="props.placeholder"
            :show-arrow="false"
            :value="props.value"
            allow-clear
            show-search
            style="width: 100%"
            @change="handleChange"
            @search="handleSearch">
    <template #notFoundContent>
      <a-spin v-if="isLoading" size="small"/>
      <div v-else>{{ notFoundPlaceholder }}</div>
    </template>
  </a-select>
</template>

<script setup>
import {Form} from 'ant-design-vue';
import {debounce} from 'lodash-es';

const props = defineProps(['control', 'placeholder', 'value', 'option']);
const emit = defineEmits(['update:value', 'update:option']);
const formItemContext = Form.useInjectFormItemContext();

const keyword = ref('');

const {data, execute, isLoading, isFinished} = useApi({
  immediate: false
});

const fetch = debounce(async keyword => {
  let url = props.control.config.searchUrl;
  if (typeof url === 'function') {
    url = url();
  }
  await execute({
    url,
    data: {
      keyword
    }
  });
}, 300);

const selectOptions = computed(() => {
  const options = data.value != null ? data.value : [...(props.control.config.initOptions ?? [])];
  const {textKey, valueKey} = props.control.config;

  return options.map(record => {
    const label = typeof textKey === 'function'
      ? textKey({record})
      : record[textKey];
    const value = valueKey == null ? record : record[valueKey];
    return {
      record,
      label,
      value
    };
  });
});

const notFoundPlaceholder = computed(() => {
  const notEmptyKeyword = keyword.value?.length > 0;
  if (notEmptyKeyword && isFinished.value && selectOptions.value.length === 0) {
    return '没有查询到记录 ~';
  }
  return props.control.config.notFoundPlaceholder ?? '请输入关键词查询 ~';
});

const handleSearch = async value => {
  keyword.value = value.trim();
  if (value.length === 0) {
    data.value = [];
  } else {
    fetch(keyword.value);
  }
};

const handleChange = async (value, option) => {
  emit('update:value', value);
  emit('update:option', option?.record);
  formItemContext.onFieldChange();
};
</script>
